package pos.Driving;

import pos.Driving.Path.Segment.Segment;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;
import javax.media.j3d.*;
import javax.vecmath.Color3f;
import pos.ControlCenter;
import pos.Driving.Camera.Camera;
import pos.Driving.Path.Segment.Segment_01_01;
import pos.Driving.Task.TaskPlayer;
import pos.Driving.Task.TaskPlayerFactory;
import pos.Driving.Train.*;
import pos.ICommand;
import pos.IModeController;
import pos.MessageBox.MessageBox;
import pos.utils.ObjectFactory;
import pos.utils.PathRes;

/**
 *
 * @author plus
 */
public class DrivingController implements IModeController {

    private HashMap<String, ICommand> CommandsPool = new HashMap<String, ICommand>();
    private Segment currentSegment;
    private Train currentTrain;
    private Camera currentCamera;
    private TaskPlayer taskPlayer;
    private boolean bLoaded = false;
    private BranchGroup CP,BGLoading;

    public DrivingController() {
        
        if (currentTrain == null) {
            new Timer().schedule(new TimerTask() {
                @Override
                public void run() {
                    initObjects();
                    BlendCommands();
                    bLoaded = true;
                    setMode();
                }
            }, 1000);
        } else {
            bLoaded = true;
        }
    }

    @Override
    public void setMode() {
        if (bLoaded) {
            BGLoading.detach();
            ControlCenter.preFrameInvoker.addLisener(currentTrain);
            ControlCenter.preFrameInvoker.addLisener(currentCamera);
            ControlCenter.preFrameInvoker.addLisener(taskPlayer);
            ControlCenter.objRoot.addChild(currentSegment);
            ControlCenter.objRoot.addChild(currentTrain.getTrainGroup());
            ControlCenter.dashBoardRoot.addChild(CP);

            ControlCenter.eventBehavior.setTarget(currentTrain.getTrainGroup(), this);
            taskPlayer.play();
            /*
            doEvent("SetSideway", new SidewayDesc(0,"Return",false,true));
            doEvent("SetSideway", new SidewayDesc(1,"Final",true,false));*/
            
        } else {
            BGLoading=new BranchGroup();
            BGLoading.setCapability(BranchGroup.ALLOW_DETACH);
            BGLoading.addChild(ObjectFactory.createTexturedSurface(
                    0.8f, 0.6f, -1f, new Color3f(1,1,1), 0,
                    PathRes.getPath("Image.DriveRoom.Loading")));
            ControlCenter.dashBoardRoot.addChild(BGLoading);
            System.out.println("Loading Objects, Please wait...");
        }
    }
    
    public void addCPChild(Node child){
        CP.addChild(child);
    }
    
    @Override
    public void disposeMode() {
        //currentRail.detach();
        currentSegment.detach();
        currentTrain.getTrainGroup().detach();
        ControlCenter.dashBoardRoot.removeAllChildren();
        ControlCenter.preFrameInvoker.removeLisener(taskPlayer);
        ControlCenter.preFrameInvoker.removeLisener(currentTrain);
        ControlCenter.preFrameInvoker.removeLisener(currentCamera);
    }

    @Override
    public Object doEvent(String EventName, Object Param) {
        ICommand InvokedCommand = CommandsPool.get(EventName);
        if (InvokedCommand != null) {
            return InvokedCommand.execute(Param);
        } else {
            String Event[]=EventName.split("@");
            InvokedCommand = CommandsPool.get(Event[0]);
            if (InvokedCommand != null) {
                return InvokedCommand.execute(Event[1]);
            }else{
                System.err.println("Event:" + EventName + " NOT found!?");
                return null;
            }
        }
    }

    private void initObjects() {
        CP=new BranchGroup();
        CP.setCapability(BranchGroup.ALLOW_DETACH);
        //currentRail = new RailTest("First Rail", 4600, this);
        currentCamera=new Camera(this);
        currentSegment = new Segment_01_01();
        currentTrain = TrainFactory.getInstance().createTrain("Data.Train.AC01.Desc",this,0);
        taskPlayer= TaskPlayerFactory.getTaskPlayer01_01(this);
    }

    /**
     * 将事件名与Command对象绑定
     */
    private void BlendCommands() {
        CommandsPool.put("KeyEvent", new CommandDrivingKeyEvent(currentTrain));
        CommandsPool.put("ChangeView", new CommandChangeView(currentCamera));
        CommandsPool.put("ResetTask", new CommandResetTask(taskPlayer));
        CommandsPool.put("GetTrain", new CommandGetTrainRef(currentTrain));
        
        CommandsPool.put("ChangeToMainMenu", new CommandChangeToMainMenu());
        
        CommandsPool.put("RefreshPosition", new CommandRefreshPosition(currentSegment));
        CommandsPool.put("GetPosPoint", new CommandGetPosPoint(currentSegment));
        CommandsPool.put("TrainAction", new CommandTrainAction(currentSegment));
        CommandsPool.put("SetSideway", new CommandSetSidewayMode(currentSegment));
        
        CommandsPool.put("SetCameraFollowingType", 
                new CommandSetCameraFollowingType(currentCamera));
        CommandsPool.put("SetCameraStatue", 
                new CommandSetCameraStatue(currentCamera));
        CommandsPool.put("SetCustomizeCamera", 
                new CommandSetCustomizeCamera(currentCamera));
        
        CommandsPool.put("GetReady", new pos.CommandMsgbox(
                new MessageBox(null, null, "准备开始", "列车已启动完毕,出发吧！",
                new String[]{"开始"},
                new String[]{"Cancel"})));
        
        CommandsPool.put("TimeOut", new pos.CommandMsgbox(
                new MessageBox(null, null, "运营事故", "列车严重晚点,运营失败",
                new String[]{"重新开始", "返回主菜单"},
                new String[]{"ResetTrain", "ChangeToMainMenu"})));
        
        CommandsPool.put("FinshTask", new pos.CommandMsgbox(
                new MessageBox(null, null,"任务完成！", "",
                new String[]{"重新执行本次任务","返回主菜单"},
                new String[]{"ResetTask", "ChangeToMainMenu"})));
        
        CommandsPool.put("PauseMsg", new pos.CommandMsgbox(
                new MessageBox(null, null, "暂停", "",
                new String[]{"更改视角", "重新开始", "返回主菜单"},
                new String[]{"ChangeViewMsg", "ResetTask", "ChangeToMainMenu"})));

        CommandsPool.put("ChangeViewMsg", new pos.CommandMsgbox(
                new MessageBox(null, null, "切换视角", "选择您要的视角",
                new String[]{"控制台视角","进路视角","车辆跟踪视角", "车厢视角", "定点跟踪视角"},
                new String[]{"ChangeView@4","ChangeView@0", "ChangeView@1", "ChangeView@2", "ChangeView@3"})));
        
    }
}
